﻿using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using HBKY.Shop.Common.Helper;
using HBKY.Shop.Common;
using HBKY.Shop.Common.LogHelper;
using NLog;

namespace HBKY.Shop.Extensions.Middleware
{
    /// <summary>
    /// 中间件
    /// 记录请求和响应数据
    /// </summary>
    public class HttpLogMiddleware
    {
        /// <summary>
        /// 
        /// </summary>
        private readonly RequestDelegate _next;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="next"></param>
        public HttpLogMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            //记录上线文请求的唯一表示 这个中间件比较靠前目前记录在这里
            //MappedDiagnosticsContext.Set("ActivityId", Guid.NewGuid());
            Trace.CorrelationManager.ActivityId = Guid.NewGuid();
            //链路traceId
            context.Response.Headers["traceId"] = Trace.CorrelationManager.ActivityId.ToString();
            // 输出当前环境标识
            context.Response.Headers["environment"] = EnvHelper.GetEnvName();

            //初始化时间
            Stopwatch stopwatch = new Stopwatch(); 
            stopwatch.Start();

            #region  执行逻辑

            if (Appsettings.Option("Middleware", "RequestResponseLog", "Enabled").ObjToBool())
            {
                // 过滤，只有接口
                if (context.Request.Path.Value.Contains("api"))
                {
                    context.Request.EnableBuffering();
                    Stream originalBody = context.Response.Body;

                    try
                    {
                        // 存储请求数据
                        await RequestDataLog(context);

                        using (var ms = new MemoryStream())
                        {
                            context.Response.Body = ms;

                            await _next(context);

                            // 存储响应数据
                            //ResponseDataLog(context.Response, ms);
                            ms.Position = 0;
                            await ms.CopyToAsync(originalBody);

                            stopwatch.Stop();
                            if (!EnvHelper.IsOnline)
                                PrettyConsoleHelper.Line($"执行耗时:{stopwatch.ElapsedMilliseconds}ms", ConsoleColor.DarkYellow);
                            LogManagerNlog.LogInformation($"执行耗时:{stopwatch.ElapsedMilliseconds}ms");
                        }
                    }
                    catch (Exception)
                    {
                         stopwatch.Stop();
                        // 记录异常
                        //ErrorLogData(context.Response, ex);
                    }
                    finally
                    {
                        context.Response.Body = originalBody;
                    }
                }
                else
                {
                    await _next(context);
                    stopwatch.Stop();
                }
            }
            else
            {
                await _next(context);
                stopwatch.Stop();
            }

            #endregion

        }

        private async Task RequestDataLog(HttpContext context)
        {
            var request = context.Request;
            var sr = new StreamReader(request.Body);

            var content = $" QueryData:{request.Path}{request.QueryString} BodyData:{await sr.ReadToEndAsync()}";

            if (!string.IsNullOrEmpty(content))
            {
                Parallel.For(0, 1, e =>
                {
                    //不单独记录 \r\n
                    //LogLock.OutSql2Log("RequestResponseLog", new string[] { "Request Data:", content });

                    LogManagerNlog.LogInformation(String.Join("|", new string[] { "RequestResponseLog RequestData:", content }));
                });

                request.Body.Position = 0;
            }
        }
    }
}
